package baseNIO;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;

/**
 * Created by mHandler on 2018/8/4 0004.
 * Description:NIO 例子
 */
public class NIOServer {
    private static int port = 8000;
    private static InetSocketAddress address = null;
    private static Selector selector;
    private static ByteBuffer buffer = ByteBuffer.allocate(1024);

    public static void main(String[] args) throws IOException {
        address = new InetSocketAddress(port);
        //channel多路复用
        ServerSocketChannel server = ServerSocketChannel.open();
        //监听一个端口
        server.bind(address);
        //设置为非诸塞
        server.configureBlocking(false);
        //初始化selector
        selector = Selector.open();
        //channel和selector关联
        server.register(selector, SelectionKey.OP_ACCEPT);//表示客户端可以进行连接请求
        //使用selector進行循環，
        while (true){
            int count = selector.select();
            if (count == 0)
                continue;
            Set<SelectionKey> keys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = keys.iterator();
            while (iterator.hasNext()){
                SelectionKey key = iterator.next();
                //对keyjinx操作
                process(key);
                iterator.remove();
            }
        }

    }

    private static void process(SelectionKey key) throws IOException {
        //判断key状态，可接收，可读写
        if (key.isAcceptable()){
            //创建连接对象，客户端对象
            ServerSocketChannel socketChannel = (ServerSocketChannel) key.channel();
            SocketChannel client = socketChannel.accept();
            client.configureBlocking(false);
            //已连接改变状态，可读
            client.register(selector,SelectionKey.OP_READ);
        }else if (key.isReadable()){
            SocketChannel client = (SocketChannel) key.channel();
            //根据客户端进行操作,接受客户端数据到buffer中
            int len = client.read(buffer);
            if (len > 0){
                buffer.flip();//对缓冲去数据进行锁定
            }
            //读完，改变状态，可写
            client.register(selector,SelectionKey.OP_WRITE);
            buffer.clear();
        }else if (key.isWritable()){
            SocketChannel client = (SocketChannel) key.channel();
            client.write(buffer.wrap("我要写回去".getBytes()));
            client.close();
        }
    }
}
